using GameBaseFramework.Base;
using GameBaseFramework.Extension;
using GameBaseFramework.FrameWorkCommand;
using GameBaseFramework.Pattern;
using GameUnityFrameWork.Resource;
using System;
using System.Collections.Generic;
using System.Linq;
using GameUnityFramework.Resource;
using Unity.VisualScripting;
using UnityEngine;


/// <summary>
/// 按当前逻辑，UI有两种存在形式
/// 一种是通过Open/Close命令进行管理，这类UI通过UIViewManager进行管理；
/// 另一种是附加在某个UI实例的_ChildList里（即UIItem），这类UI通过父类的UIViewBase进行管理;
/// 尽量不要通过UnityObjectManager甚至Addressable直接加载UIView，这会导致UIViewManager丢失对UIView的管理。
/// </summary>
namespace GameUnityFramework.UIView
{
    /// <summary>
    /// 优先级
    /// </summary>
    public enum UIViewPriority
    {
        Level0,
        Level1,
        Level2,
        Level3,
        Level4,
        Level5,
        Level6,
        Level7,
        Level8,
        Level9,
        Max
    }

    /// <summary>
    /// UIView打开的方式
    /// </summary>
    public enum UIViewOpenType
    {
        /// <summary>
        /// 直接覆盖在现有的UIView上，不对其他UIView进行处理
        /// </summary>
        Overlying,

        /// <summary>
        /// 关闭其他除了Forever的UIView，只保留当前UI
        /// </summary>
        Replace,

        /// <summary>
        /// 永久，不会被关闭
        /// </summary>
        Forever
    }


    /// <summary>
    /// UIView管理器，单例模式
    /// </summary>
    public class UIViewManager : MonoBehaviour, Icommand, IResourceLoader
    {
        private static UIViewManager _instance;

        public static UIViewManager Instance
        {
            get
            {
                if (_instance == null)
                {
                    _instance = GameObject.Find("UIViewRoot").GetOrAddComponent<UIViewManager>();
                }
                return _instance;
            }
        }

        /// <summary>
        /// UI Canvas
        /// </summary>
        public Canvas Canvas;

        /// <summary>
        /// 所有的优先级节点
        /// </summary>
        public static Transform[] _priorityTransforms = new Transform[(int)EViewPriority.Max + 1];

        /// <summary>
        /// 当前除了永驻UI外的所有UI
        /// </summary>
        private List<Transform> _curUIViews = new List<Transform>();

        /// <summary>
        /// 初始化
        /// </summary>
        public void Awake()
        {
            if (_instance == null)
                _instance = this;
            else
            {
                DebugTool.Log("出现了多个UIViewRoot");
            }
            Canvas = GetComponent<Canvas>();
            for (var i = 0; i < _priorityTransforms.Length; i++)
            {
                _priorityTransforms[i] = Canvas.transform.Find($"Priority{i}");
            }
            this.BindCommand<UIViewOpenCommand>(OnUIViewOpenCommand);
            DontDestroyOnLoad(this);
        }

        /// <summary>
        /// 销毁
        /// </summary>
        private void OnDestroy()
        {
            this.UnBindAllSelfCommands();
        }

        /// <summary>
        /// Open UIView
        /// </summary>
        public void Open<T>(object data = null, Transform parent = null) where T : UIViewBase
        {
            Open<T>(data, parent, EViewOpenType.Replace, EViewPriority.Level1, string.Empty);
        }

        /// <summary>
        /// Open UIView
        /// </summary>
        public void Open<T>(object data, Transform parent, EViewOpenType openType, EViewPriority priority, string prefabPath, Action EndEvent = null, Action EnterEvent = null) where T : UIViewBase
        {
            if (string.IsNullOrEmpty(prefabPath))
            {
                prefabPath = typeof(T).Name;
            }
            if (parent == null) parent = _priorityTransforms[(int)priority];
            this.InstantiateAsync(prefabPath, parent, (go) =>
            {
                EnterEvent?.Invoke();
                Open<T>(data, go, EndEvent, openType);
            });
        }

        /// <summary>
        /// 添加当前界面EndEvent重载
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="go"></param>
        /// <param name="openType"></param>
        /// <param name="endEvent">View被销毁时调用的事件</param>
        private void Open<T>(object data, GameObject go, Action endEvent, EViewOpenType openType = EViewOpenType.Replace) where T : UIViewBase
        {
            var view = go.GetOrAddComponent<T>();
            view.Init(this, data);
            view._EndEvent = endEvent;
            AddUIView(go, openType);
        }

        /// <summary>
        /// 添加当前界面
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="go"></param>
        public void Open<T>(object data, GameObject go, EViewOpenType openType = EViewOpenType.Replace) where T : UIViewBase
        {
            var view = go.GetOrAddComponent<T>();
            view.Init(this, data);
            AddUIView(go, openType);
        }

        /// <summary>
        /// 添加界面到字典中
        /// </summary>
        /// <param name="go"></param>
        /// <param name="openType"></param>
        private void AddUIView(GameObject go, EViewOpenType openType)
        {
            if (openType == EViewOpenType.Replace)
            {
                for (var i = 0; i < _curUIViews.Count; i++)
                {
                    if (_curUIViews[i] != null)
                    {
                        try
                        {
                            var viewGO = _curUIViews[i].gameObject;
                            var mono = viewGO.GetComponent<UIViewBase>();
                            if (mono != null)
                            {
                                mono.Close();
                            }
                            else
                            {
                                if (viewGO != null)
                                {
                                    GameObject.Destroy(viewGO);
                                }
                            }
                        }
                        catch (Exception e)
                        {
                            DebugTool.LogError(e.StackTrace + e.Message);
                        }
                    }
                }
                _curUIViews.Clear();
            }
            _curUIViews.Add(go.transform);
        }

        /// <summary>
        /// 接收指令打开界面
        /// </summary>
        /// <param name="command"></param>
        private void OnUIViewOpenCommand(UIViewOpenCommand command)
        {
            var data = command.Data;
            var parent = command.Parent;
            var viewType = command.ViewType;
            var openType = command.ViewOpenType;
            var priority = command.ViewPriority;
            if (parent == null) parent = _priorityTransforms[(int)priority];
            var prefabName = viewType.Name;
            this.InstantiateAsync(prefabName, parent, (go) =>
            {
                var view = go.GetOrAddComponent(viewType) as UIViewBase;
                view.Init(this, data);
                AddUIView(go, openType);
            });
        }

    }
}

